#include "GObservable.h"
#include "GObserver.h"

#include <algorithm>

namespace GUtil
{

	GObservable::GObservable()
	{
		ObserverMask.RaiseAll();
	}

	GObservable::~GObservable()
	{
		NotifyObservers(G_OM_STOP_OBSERVING, NULL);

		Observers.clear();
	}

	void GObservable::SetObserverMask(GObserverType Mask)
	{
		ObserverMask = Mask;
	}

	GObserverType GObservable::GetObserverMask() const
	{
		return ObserverMask;
	}

	void GObservable::AppendObserver(GObserver* Observer)
	{
		Observers.push_back(Observer);
		Observer->AppendObservable(this);
	}

	void GObservable::RemoveObserver(GObserver* Observer)
	{
		ObserverList::iterator Iter;
		Iter = std::find(Observers.begin(), Observers.end(), Observer);
		Observers.erase(Iter);

		Observer->HandleMessage(this, G_OM_STOP_OBSERVING, NULL);
		Observer->RemoveObservable(this);
	}

	bool GObservable::CanNotifyObserver(GObserver* Observer) const
	{
		return ObserverMask.Contains(Observer->GetObserverType());
	}

	void GObservable::NotifyObservers(GMessageId Message, void* Data)
	{
		ObserverList::iterator End = Observers.end();
		ObserverList::iterator Current = Observers.begin();

		while (Current != End)
		{
			GObserver* Observer = *Current;
			
			if (CanNotifyObserver(Observer))
			{
				Observer->HandleMessage(this, Message, Data);
			}

			Current++;
		}
	}

};